package com.agile.leetcode.hash;

import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 不带虚拟节点的一致性hash算法的实现
 *
 * @Author KD
 * @Date 2021/2/5 9:35
 */
@SuppressWarnings("all")
public class ConsistencyHashWithoutVirtualNode {
    /**
     * 初始化ip
     */
    private static String[] ip = {"192.168.89.4", "192.168.89.5", "192.168.89.8", "192.168.89.9"};
    private static SortedMap<Integer, String> sortedMap = new TreeMap<Integer, String>();

    /**
     * 初始化服务器位置
     */
    static {
        for (String s : ip) {
            // 拿到hash值
            int hash = getHash(s);
            System.out.println("服务器" + s + "的hash值是" + hash);
            sortedMap.put(hash, s);
        }
    }

    /**
     * 拿到服务器
     *
     * @param str
     * @return
     */
    public static String getServer(String str) {
        // 拿到哈希值
        int hash = getHash(str);
        // 拿到所有大于该hash值得server
        SortedMap<Integer, String> tailMap = sortedMap.tailMap(hash);
        //
        if (tailMap.isEmpty()) {
            // 没有比他大的
            // 从第一个节点开始
            Integer integer = sortedMap.firstKey();
            // 拿到该服务器
            return sortedMap.get(integer);
        } else {
            // 拿到第一个节点
            Integer integer = tailMap.firstKey();
            return tailMap.get(integer);
        }
    }

    public static int getHash(String ip) {
        final int p = 16777619;
        int hash = (int) 2166136261L;
        for (int i = 0; i < ip.length(); i++)
            hash = (hash ^ ip.charAt(i)) * p;
        hash += hash << 13;
        hash ^= hash >> 7;
        hash += hash << 3;
        hash ^= hash >> 17;
        hash += hash << 5;

        // 如果算出来的值为负数则取其绝对值
        if (hash < 0)
            hash = Math.abs(hash);
        return hash;
    }

    public static void main(String[] args) {
        String[] str = {"詹姆斯", "杜兰特", "安东尼", "韦德", "保罗"};
        for (String s : str) {
            String server = getServer(s);
            System.out.println(s + "落在的服务器是" + server);
        }
    }
}
